package com.css.zfzx.sjcj.modules.yhdisaster.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.util.ReflectUtil;
import com.alibaba.fastjson.JSONObject;
import com.css.bpm.platform.api.local.PlatformAPI;
import com.css.bpm.platform.sys.dict.repository.entity.DictItemEntity;
import com.css.bpm.platform.utils.*;
import com.css.zfzx.sjcj.common.ConstantInfo;
import com.css.zfzx.sjcj.common.utils.*;
import com.css.zfzx.sjcj.modules.yhdisaster.repository.YhDisasterNativeRepository;
import com.css.zfzx.sjcj.modules.yhdisaster.repository.YhDisasterRepository;
import com.css.zfzx.sjcj.modules.yhdisaster.repository.entity.AssessEntity.*;
import com.css.zfzx.sjcj.modules.yhdisaster.repository.entity.YhDisasterEntity;
import com.css.zfzx.sjcj.modules.yhdisaster.service.YhDisasterService;
import com.css.zfzx.sjcj.modules.yhdisaster.viewobjects.CheckVO;
import com.css.zfzx.sjcj.modules.yhdisaster.viewobjects.YhDisasterQueryParams;
import com.css.zfzx.sjcj.modules.yhdisaster.viewobjects.YhDisasterVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lxg
 * @date 2020-11-10
 */
@Service
public class YhDisasterServiceImpl implements YhDisasterService {

	@Autowired
    private YhDisasterRepository yhDisasterRepository;
    @Autowired
    private YhDisasterNativeRepository yhDisasterNativeRepository;

    @Value("${transactional.commit.size:10000}")
    private int commitSize;

    @PersistenceContext
    private EntityManager entityManager;


    @Override
    public JSONObject queryYhDisasters(YhDisasterQueryParams queryParams, int curPage, int pageSize, String type, String sort, String order) {
        if (!PlatformObjectUtils.isEmpty(sort) && sort.length() > 0){
            sort= CheckObjFields.propertyChange(sort);
        }
        Page<YhDisasterEntity> yhDisasterPage = this.yhDisasterNativeRepository.queryYhDisasters(queryParams, curPage, pageSize,type,sort,order);
        JSONObject jsonObject = PlatformPageUtils.formatPageData(yhDisasterPage);
        return jsonObject;
    }


    @Override
    public YhDisasterEntity getYhDisaster(String id) {
        YhDisasterEntity yhDisaster = this.yhDisasterRepository.findById(id).orElse(null);
         return yhDisaster;
    }

    @Override
    public YhDisasterEntity getYhDisaster(String id, String province) {
        String provinceSubfix = PinyinUtil.buildProvinceSubfix(province);
        String findByIdAndIsValidAndProvinceSql = "select * from yh_disaster"+provinceSubfix+" where id ='"+id+"' AND is_valid='1'";
        Query findByIdAndIsValidAndProvinceQuery = entityManager.createNativeQuery(findByIdAndIsValidAndProvinceSql, YhDisasterEntity.class);
        return (YhDisasterEntity) findByIdAndIsValidAndProvinceQuery.getSingleResult();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public YhDisasterEntity saveYhDisaster(YhDisasterEntity yhDisaster, String type) {
        String uuid = UUIDGenerator.getUUID();
        yhDisaster.setId(uuid);
        yhDisaster.setCreateUserId(PlatformSessionUtils.getUserId());
        yhDisaster.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
        yhDisaster.setIsValid("1");
        yhDisaster.setYhProjectType(type);
        yhDisaster.setEvaluationResult("0");
        this.yhDisasterRepository.save(yhDisaster);
        return yhDisaster;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public YhDisasterEntity updateYhDisaster(YhDisasterEntity yhDisaster) {
        //逻辑步骤，存在评估时可以修改数据的情况
        //从数据库中查询出数据
        String provinceSubfix = PinyinUtil.buildProvinceSubfix(yhDisaster.getProvince());
        YhDisasterEntity yhDisasterEntity = null;
        String findByIdAndIsValidAndProvinceSql = "select * from yh_disaster"+provinceSubfix+" where id ='"+yhDisaster.getId()+"' AND is_valid='1'";
        Query findByIdAndIsValidAndProvinceQuery = entityManager.createNativeQuery(findByIdAndIsValidAndProvinceSql, YhDisasterEntity.class);
        yhDisasterEntity =(YhDisasterEntity) findByIdAndIsValidAndProvinceQuery.getSingleResult();
        //查询的数据和表单数据比对，将数据库中查询的数据和表单不一致的已以及表单中例如创建时间这样的为空的数据从数据库中复制
        compareData(yhDisaster,yhDisasterEntity);
        //将表单数据转换成各省的子实例
        YhDisasterEntity1 disasterEntity = getChildisasterEntity(yhDisaster);
        BeanUtils.copyProperties(yhDisaster,disasterEntity);
        //将子实例的数据更新到数据表中去。
        String userId = PlatformSessionUtils.getUserId();
        disasterEntity.setUpdateUser(userId);
        disasterEntity.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
        disasterEntity.setReviewStatus("1");
        disasterEntity.setIsValid("1");
        StringBuilder builder = new StringBuilder();
        builder.append("update yh_disaster").append(provinceSubfix).append(" set ");
        String updateSql = buildUpdateFieldSql(disasterEntity);
        builder.append(updateSql);
        Query query = entityManager.createNativeQuery(builder.toString());
        int i = query.executeUpdate();
//        YhDisasterEntity yhDisasterEntity = yhDisasterRepository.findByIdAndIsValid(yhDisaster.getId(), "1");
//        UpdateUtil.copyNullProperties(yhDisasterEntity, yhDisaster);
//        String userId = PlatformSessionUtils.getUserId();
//        //yhDisaster.setEvaluationResult("0");
//        yhDisaster.setUpdateUser(userId);
//        yhDisaster.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
//        yhDisaster.setReviewStatus("1");
//        yhDisaster.setIsValid("1");
//        this.yhDisasterRepository.save(yhDisaster);
        return yhDisaster;
    }
    private String buildUpdateFieldSql(YhDisasterEntity1 yhDisaster) {
        StringBuilder fieldBuilder = new StringBuilder("");
        Field[] fields = ReflectUtil.getFields(yhDisaster.getClass());
        AtomicInteger integer = new AtomicInteger(0);
        String idValue = "";
        for (Field field : fields) {
            Class<?> type = field.getType();
            field.setAccessible(true);
            String name = field.getName();

            Object value = ReflectUtil.getFieldValue(yhDisaster, field);
            name = StringUtil.humpToUnderline(name);
            if("id".equals(name)){
                idValue =(String) value;
                continue;
            }
            fieldBuilder.append(name).append("=");
            if(name.equals("is_up_to_standard")){
        System.out.println("1");
            }
            if(type.getName().equals("java.util.Date")){
                SimpleDateFormat simpleDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                value = (value==null?null:"'"+ Timestamp.valueOf(simpleDate.format(value))+"'");
            }else if(type.getName().equals("java.lang.Double")){
                value = (value==null?0.0:"'"+value+"'");
            }else if(type.getName().equals("java.lang.Integer")){
                value = (value==null?0:"'"+value+"'");
            }else{
                value = (value==null?"''":"'"+value+"'");
            }
            fieldBuilder.append(value);
            if(integer.get()<fields.length-1){
                fieldBuilder.append(",");
            }
        }
        String s = fieldBuilder.toString();
        if(s.charAt(s.length()-1) == ',') { //s.length()-1获取字符串最后一位字符的索引，传入charAt方法获取索引对应的字符，判断是否为逗号
            s = s.substring(0,s.length()-1);
        }
        String whereSql = " where id= '"+idValue+"'";
        return s + whereSql;
    }
    private YhDisasterEntity1 getChildisasterEntity(YhDisasterEntity entity) {
        String pinyinOfProvince = "";
        if(org.apache.commons.lang.StringUtils.isNotBlank(entity.getProvince())){
            pinyinOfProvince = PinyinUtil.getPinyin(entity.getProvince());
            if("山西省".equals(entity.getProvince())){
                pinyinOfProvince = (pinyinOfProvince+"1");
            }
        }
        switch (pinyinOfProvince){
            case "beijingshi":
                return new YhDisaster11Entity();
            case "tianjinshi":
                return new YhDisaster12Entity();
            case "shanghaishi":
                return new YhDisaster31Entity();
            case "chongqingshi":
                return new YhDisaster50Entity();
            case "heilongjiangsheng":
                return new YhDisaster23Entity();
            case "jilinsheng":
                return new YhDisaster22Entity();
            case "liaoningsheng":
                return new YhDisaster21Entity();
            case "anhuisheng":
                return new YhDisaster34Entity();
            case "fujiansheng":
                return new YhDisaster35Entity();
            case "gansusheng":
                return new YhDisaster62Entity();
            case "guangdongsheng":
                return new YhDisaster44Entity();
            case "guangxizhuangzuzizhiqu":
                return new YhDisaster45Entity();
            case "guizhousheng":
                return new YhDisaster52Entity();
            case "hainansheng":
                return new YhDisaster46Entity();
            case "hebeisheng":
                return new YhDisaster13Entity();
            case "henansheng":
                return new YhDisaster41Entity();
            case "hubeisheng":
                return new YhDisaster42Entity();
            case "hunansheng":
                return new YhDisaster43Entity();
            case "jiangsusheng":
                return new YhDisaster32Entity();
            case "jiangxisheng":
                return new YhDisaster36Entity();
            case "neimengguzizhiqu":
                return new YhDisaster15Entity();
            case "ningxiahuizuzizhiqu":
                return new YhDisaster64Entity();
            case "qinghaisheng":
                return new YhDisaster63Entity();
            case "shandongsheng":
                return new YhDisaster37Entity();
            case "shanxisheng":
                return new YhDisaster61Entity();
            case "shanxisheng1":
                return new YhDisaster14Entity();
            case "sichuansheng":
                return new YhDisaster51Entity();
//            case "taiwansheng":
//                return new YhTaiwanDisasterUpdateVo();
            case "xinjiangweiwuerzizhiqu":
                return new YhDisaster65Entity();
            case "xizangzizhiqu":
                return new YhDisaster54Entity();
            case "yunnansheng":
                return new YhDisaster53Entity();
            case "zhejiangsheng":
                return new YhDisaster33Entity();
            case "xinjiangshengchanjianshebingtuan":
                return new YhDisaster66Entity();
//            case "xianggangtebiexingzhengqu":
//                return new YhXianggangDisasterUpdateVo();
//            case "aomentebiexingzhengqu":
//                return new YhAomenDisasterUpdateVo();
            default:
                return new YhDisaster11Entity();
        }
    }

    private void compareData(YhDisasterEntity yhDisaster, YhDisasterEntity yhDisasterEntity) {
        Field[] fields = ReflectUtil.getFields(yhDisaster.getClass());
        for (Field field : fields) {
            field.setAccessible(true);
            Object disasterValue = ReflectUtil.getFieldValue(yhDisaster, field);
            Object disasterEntityValue = ReflectUtil.getFieldValue(yhDisasterEntity, field);
            if(disasterValue==null || "".equals(disasterValue)){
                disasterValue = disasterEntityValue;
            }
            ReflectUtil.setFieldValue(yhDisaster,field,disasterValue);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteYhDisasters(List<String> ids) {
        List<YhDisasterEntity> yhDisasterList = this.yhDisasterRepository.findAllById(ids);
        if(!PlatformObjectUtils.isEmpty(yhDisasterList) && yhDisasterList.size() > 0) {
            for(YhDisasterEntity yhDisaster : yhDisasterList) {
                yhDisaster.setIsValid("0");
                this.yhDisasterRepository.save(yhDisaster);
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteYhDisasterList(String ids) {
        String[] split = ids.split(",");
        List<String> idList = new ArrayList<String>(split.length);
        for (String s : split) {
            idList.add(s.split("_")[0]);
        }
        String[] strs = idList.toArray(new String[]{});
        String insql = this.buildInSql(strs);
        //删除时只能按照某省删除
        String provinceSubfix = PinyinUtil.buildProvinceSubfix(split[0].split("_")[1]);
        StringBuilder builder = new StringBuilder();
        builder.append("update yh_disaster").append(provinceSubfix).append(" set is_valid=0");
        builder.append(" where id in (").append(insql).append(")");
        Query query = entityManager.createNativeQuery(builder.toString());
        query.executeUpdate();
    }

    @Override
    public List<DictItemEntity> getValidDictItemsByDictCode(String dictCode) {
        List<DictItemEntity> validDictItems = PlatformAPI.getDictAPI().getValidDictItemsByDictCode(dictCode);
        return validDictItems;
    }

    @Override
    public String importExcel(MultipartFile file, HttpServletResponse response) {
        try {
            // 返回的消息
            StringBuilder returnMsg = new StringBuilder();
            // 导入的参数信息
            ImportParams params = new ImportParams();
            // 设置简析的第一行
            params.setTitleRows (1);
            params.setHeadRows(1);
            // 是否需要校验
           // params.setNeedVerify(true);
            // 获取到Excel数据
            ExcelImportResult<YhDisasterVO> result = ExcelImportUtil.importExcelMore(file.getInputStream(), YhDisasterVO.class, params);
            List<YhDisasterVO> list = result.getList();
            // Excel条数据
            int firstList = list.size();
            StringBuilder sb = new StringBuilder();
            // 业务主键不存在的条数
            int failCount = saveDisasterList(list, sb);
            if (failCount > 0) {
                // result.getFailList().size()为保存时出错的条数
                int failList = firstList + result.getFailList().size() - list.size();
                returnMsg.append("成功导入" + (result.getList().size() - failCount) + "条，失败" + (failList + failCount) + "条<br/>");
                returnMsg.append("业务主键" + failCount + "不存在的数据<br/>");
                returnMsg.append(sb);
            } else {
                returnMsg.append("成功导入" + (result.getList().size() - failCount) + "条，失败" + (result.getFailList().size() + failCount) + "条<br/>");
                returnMsg.append(sb);
            }
            if (result.isVerifyFail()) {
                // 校验返回失败行信息
                Iterator<YhDisasterVO> iterator = result.getFailList().iterator();
                while (iterator.hasNext()) {
                    YhDisasterVO yhDisasterVO = iterator.next();
                    String error = "";
                    returnMsg.append("第" + yhDisasterVO.getRowNum() + "行" + yhDisasterVO.getErrorMsg() + "<br/>");
                    returnMsg.append(error);
                }
            }
            return returnMsg.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return "导入失败，请检查数据正确性";
        }
    }

    @Override
    public void submitYhDisaster(String ids) {
        String[] split = ids.split(",");
        List<String> list=new ArrayList<>(Arrays.asList(split));
        List<YhDisasterEntity> yhDisasterEntities = yhDisasterRepository.findAllById(list);
        for (YhDisasterEntity entity:yhDisasterEntities) {
            entity.setReviewStatus("1");
            yhDisasterRepository.save(entity);
        }
    }

    @Override
    public void exportFile(YhDisasterQueryParams queryParams, String type, HttpServletResponse response) {
        List<YhDisasterEntity> yhDisasterEntities = yhDisasterNativeRepository.exportYhDisasters(queryParams, type);
        List<YhDisasterVO> list=new ArrayList<>();
        for (YhDisasterEntity entity:yhDisasterEntities) {
            String extends1 = entity.getExtends1();
            if (!org.apache.commons.lang3.StringUtils.isEmpty(extends1)) {
                switch (extends1) {
                    case ConstantInfo.TYPE_CITY_HOUSE_CH:
                        extends1 = ConstantInfo.TYPE_CITY_HOUSE_DISC;
                        break;
                    case ConstantInfo.TYPE_CITY_NO_HOUSE_CH:
                        extends1 = ConstantInfo.TYPE_CITY_NO_HOUSE_DISC;
                        break;
                    case ConstantInfo.TYPE_COUNTRY_JH_HOUSE_CH:
                        extends1 = ConstantInfo.TYPE_COUNTRY_JH_HOUSE_DISC;
                        break;
                    case ConstantInfo.TYPE_COUNTRY_DL_HOUSE_CH:
                        extends1 = ConstantInfo.TYPE_COUNTRY_DL_HOUSE_DISC;
                        break;
                    case ConstantInfo.TYPE_COUNTRY_NO_HOUSE_CH:
                        extends1 = ConstantInfo.TYPE_COUNTRY_NO_HOUSE_DISC;
                        break;
                    case ConstantInfo.TYPE_BRIDGE_CH:
                        extends1 = ConstantInfo.TYPE_BRIDGE_DISC;
                        break;
                    case ConstantInfo.TYPE_WATER_FACTILITY_CH:
                        extends1 = ConstantInfo.TYPE_WATER_FACTILITY_DISC;
                        break;
                }
                entity.setExtends1(extends1);
            }
            YhDisasterVO yhDisasterVO=new YhDisasterVO();
            BeanUtils.copyProperties(entity,yhDisasterVO);
            list.add(yhDisasterVO);
        }
        EasyPoiExcelUtil.exportExcel(list,"重点隐患数据","重点隐患数据", YhDisasterVO.class,"重点隐患数据.xls",response);
    }
//    @Transactional
//    @Override
//    public void listCheck(CheckVO checkVO) {
//        List<String> idList = Arrays.asList(checkVO.getId().split(","));
//        yhDisasterRepository.updateData(checkVO.getStatus(),checkVO.getReason(),idList);
//    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void listCheck(CheckVO checkVO) {
        String provinceSubfix = PinyinUtil.buildProvinceSubfix(checkVO.getProvince());
        String sql = buildInSql(checkVO.getId().split(","));
        StringBuilder builder = new StringBuilder();
        builder.append("update yh_disaster").append(provinceSubfix).append(" set ");
        builder.append(" quality_result=").append("'").append(checkVO.getStatus()).append("'").append(",");
        builder.append(" qualityinspection_comments=").append("'").append(checkVO.getReason()).append("'");
        builder.append(" where id in (").append(sql).append(")");
        Query query = entityManager.createNativeQuery(builder.toString());
        int i = query.executeUpdate();
    }

    private String buildInSql(String[] split) {
        // '','',''
        StringBuilder builder = new StringBuilder();
        if (split != null && split.length > 0) {
            for (String s : split) {
                builder.append("'").append(s).append("',");
            }
        }
        return builder.substring(0, builder.length() - 1).toString();
    }

//    @Override
//    public void dataQualityCheck(YhDisasterQueryParams queryParams, String type) {
//        List<YhDisasterEntity> yhDisasterEntities = yhDisasterNativeRepository.exportYhDisasters(queryParams, type);
//        List<YhDisasterEntity> saveEntities=new ArrayList<>();
//        if (yhDisasterEntities.size()<=0||yhDisasterEntities.isEmpty()){
//            return;
//        }
//        String qualityComments = "";
//        String qualityResult = "";
//        if ("1".equals(queryParams.getStatus())){
//            qualityComments = "人工质检通过！";
//        }else {
//            qualityComments = queryParams.getQualityComments();
//        }
//        qualityResult=queryParams.getStatus();
//        for (YhDisasterEntity entity:yhDisasterEntities) {
//            entity.setQualityResult(qualityResult);
//            entity.setQualityinspectionComments(qualityComments);
//            saveEntities.add(entity);
//        }
//        if (saveEntities.size() < commitSize) {
//            yhDisasterNativeRepository.batchUpdate(saveEntities);
//        } else {
//            int size = saveEntities.size() / commitSize;
//            if (saveEntities.size() % commitSize != 0) {
//                size++;
//            }
//            for (int i = 0; i < size; i++) {
//                List<YhDisasterEntity> subList = new ArrayList<>();
//                if ((i + 1) * commitSize > saveEntities.size()) {
//                    subList = saveEntities.subList(i * commitSize , saveEntities.size());
//                    System.out.println("===========当前提交数据位置:  "+ saveEntities.size());
//                } else {
//                    subList = saveEntities.subList(i * commitSize, (i + 1) * commitSize);
//                    System.out.println("===========当前提交数据位置:  "+(i + 1) * commitSize);
//                }
//                yhDisasterNativeRepository.batchUpdate(subList);
//            }
//        }
//    }
    @Override
    public void dataQualityCheck(YhDisasterQueryParams queryParams, String type) {
        List<YhDisasterEntity> yhDisasterEntities = yhDisasterNativeRepository.exportYhDisasters(queryParams, type);
        List<YhDisasterEntity1> saveEntities=new ArrayList<>();
        if (yhDisasterEntities.size()<=0||yhDisasterEntities.isEmpty()){
            return;
        }
        String qualityComments = "";
        String qualityResult = "";
        if ("1".equals(queryParams.getStatus())){
            qualityComments = "人工质检通过！";
        }else {
            qualityComments = queryParams.getQualityComments();
        }
        qualityResult=queryParams.getStatus();
        for (YhDisasterEntity entity:yhDisasterEntities) {
            YhDisasterEntity1 disasterEntity = getChildisasterEntity(entity);
            BeanUtils.copyProperties(entity,disasterEntity);
            disasterEntity.setQualityResult(qualityResult);
            disasterEntity.setQualityinspectionComments(qualityComments);

            saveEntities.add(disasterEntity);
        }
        if (saveEntities.size() < commitSize) {
            yhDisasterNativeRepository.batchUpdate(saveEntities);
        } else {
            int size = saveEntities.size() / commitSize;
            if (saveEntities.size() % commitSize != 0) {
                size++;
            }
            for (int i = 0; i < size; i++) {
                List<YhDisasterEntity1> subList = new ArrayList<>();
                if ((i + 1) * commitSize > saveEntities.size()) {
                    subList = saveEntities.subList(i * commitSize , saveEntities.size());
                    System.out.println("===========当前提交数据位置:  "+ saveEntities.size());
                } else {
                    subList = saveEntities.subList(i * commitSize, (i + 1) * commitSize);
                    System.out.println("===========当前提交数据位置:  "+(i + 1) * commitSize);
                }
                yhDisasterNativeRepository.batchUpdate(subList);
            }
        }
    }


    /**
     * 批量存入库表并且返回错误数量
     *
     * @param list
     * @param message
     * @return
     */
    public int saveDisasterList(List<YhDisasterVO> list, StringBuilder message) {
        int count = 0;
        for (int i = 0; i < list.size(); i++) {
            YhDisasterEntity yhDisasterEntity = new YhDisasterEntity();
            YhDisasterVO yhDisasterVO = list.get(i);
            // 将VO数据映射拷贝到库表中
            BeanUtil.copyPropertiesIgnoreNull(yhDisasterVO, yhDisasterEntity);
            String isValid="1";
            // 根据样本编号判断重复导入性
            List<YhDisasterEntity> yhDisasterEntityList = yhDisasterRepository.findByYhCodeAndIsValid(yhDisasterVO.getYhCode(),isValid);
            if (yhDisasterEntityList.size()==0) {
                message.append("编号不能为空不存在,也不可修改，请查看是否为导出数据，质检系统只能通过导入质检");
                ++count;
            } else {
                // 将不为null的数据拷贝到旧数据中，然后更新
                BeanUtil.copyPropertiesIgnoreNull(yhDisasterEntity, yhDisasterEntityList);
                updateYhDisaster(yhDisasterEntity);
            }
        }
        return count;
    }


}
